package com.andova.pipeline.impl

import android.os.Handler
import android.os.HandlerThread
import android.os.Message
import com.andova.ext.e
import com.andova.pipeline.Pipeline

class EventPipeline private constructor(name: String) : Pipeline {
    companion object {
        fun create(name: String): EventPipeline = EventPipeline(name)
    }

    private val lock = Object()
    private val mHandlerThread: HandlerThread = HandlerThread(name)
    private val mHandler: Handler
    private var start = false

    init {
        mHandlerThread.start()
        mHandler = object : Handler(mHandlerThread.looper) {
            override fun handleMessage(msg: Message) {
                val event = msg.obj
                (event as? Runnable)?.run()
            }
        }
        start = true
    }

    override fun queueEvent(event: Runnable, front: Boolean) {
        if (!start) {
            e("EventPipeline has quited")
            return
        }
        if (front) mHandler.sendMessageAtFrontOfQueue(mHandler.obtainMessage(0, event)) else mHandler.sendMessage(mHandler.obtainMessage(0, event))
    }

    override fun queueEvent(event: Runnable, delayed: Long) {
        if (!start) {
            e("EventPipeline has quited")
            return
        }
        mHandler.sendMessageDelayed(mHandler.obtainMessage(0, event), delayed)
    }

    override fun quit() {
        if (!start) {
            e("EventPipeline has quited")
            return
        }
        start = false
        mHandlerThread.interrupt()
        mHandlerThread.quitSafely()
    }

    override fun started(): Boolean = start
    override fun getName(): String = mHandlerThread.name
    override fun getHandler(): Handler = mHandler
    override fun wake() = run { synchronized(lock) { lock.notifyAll() } }
    override fun sleep() = run { queueEvent(Runnable { synchronized(lock) { lock.wait() } }) }
}